Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by www.netzwerkartist.de...

 << zurück
Visual C# 2005 von Andreas Kühnel
Das umfassende Handbuch
Buch: Visual C# 2005

Visual C# 2005
1.320 S., mit 2 CDs, 59,90 Euro
Galileo Computing
ISBN 3-89842-586-X
gp Kapitel 5 Das Klassendesign (Teil 2)
  gp 5.1 Statische Klassenkomponenten
    gp 5.1.1 Die Realisierung eines Objektzählers
    gp 5.1.2 Zugriff auf statische Komponenten
    gp 5.1.3 Statische Klassenvariable in der Klasse »Circle«
    gp 5.1.4 Klassenspezifische Methoden
    gp 5.1.5 Statische Methoden in der Klasse »Circle«
    gp 5.1.6 Statische Klasseninitialisierer
    gp 5.1.7 Statische Klassen
    gp 5.1.8 Zusammenfassung
  gp 5.2 Delegate – Methodenzeiger unter .NET
    gp 5.2.1 Einführung in das Prinzip der Delegate
    gp 5.2.2 Zusammenfassung der Arbeitsschritte
    gp 5.2.3 Vereinfachter Aufruf eines Delegaten
    gp 5.2.4 Anonyme Methoden
  gp 5.3 Ereignisse eines Objekts
    gp 5.3.1 Ergänzung eines Ereignisses in einer Ereignisquelle
    gp 5.3.2 Die Behandlung eines Ereignisses im Ereignisempfänger
    gp 5.3.3 Wenn der Ereignisempfänger ein Ereignis nicht behandelt
    gp 5.3.4 Ereignisse mit Übergabeparameter
    gp 5.3.5 Zusammenfassung
  gp 5.4 Strukturen – eine Sonderform der Klassen
    gp 5.4.1 Die Definition einer Struktur
    gp 5.4.2 Initialisieren einer Struktur
    gp 5.4.3 Weitere Merkmale einer Struktur
    gp 5.4.4 Verschachtelung von Strukturen
    gp 5.4.5 Änderung der Klasse »Circle«
    gp 5.4.6 Zusammenfassung
  gp 5.5 Enumerationen (Aufzählungen)
    gp 5.5.1 Wertzuweisung an enum-Mitglieder
    gp 5.5.2 Alle Mitglieder einer Aufzählung durchlaufen
  gp 5.6 Referenz- und Wertetypen
    gp 5.6.1 Typumwandlung mit Boxing
    gp 5.6.2 Die Unboxing-Konvertierung
    gp 5.6.3 Zusammenfassung
  gp 5.7 Namensräume (Namespaces)
    gp 5.7.1 Zugriff auf Namespaces
    gp 5.7.2 Die »using«-Direktive
    gp 5.7.3 Vermeiden von Mehrdeutigkeiten
    gp 5.7.4 Aufrufe mit dem »::«-Operator umleiten
    gp 5.7.5 Namespaces festlegen
    gp 5.7.6 Zusammenfassung


Galileo Computing

5.7 Namensräume (Namespacesdowntop

Die .NET-Klassenbibliothek enthält ungezählte Klassendefinitionen, die dem Entwickler im Bedarfsfall ihre individuellen Dienste über Methoden bereitstellen. Es kann davon ausgegangen werden, dass sich das Angebot im Laufe der Zeit durch neue Technologien noch deutlich erweitern wird. Dabei sind die benutzerdefinierten Klassen noch nicht berücksichtigt.

Gäbe es für dieses große Angebot keine besondere Verwaltungsstruktur, wäre das Chaos perfekt. Erfahrene Entwickler wissen, wie schwierig es ist, aus den ca. 5000 bis 6000 verschiedenen Betriebssystemfunktionen eines 32-Bit-Windows-Betriebssystems eine bestimmte zu finden, die genau das leistet, was an Funktionalität gesucht wird. Da hilft auch kein seitens Microsoft sorgfältig gewählter, beschreibender Funktionsname weiter: Die Suche gleicht der nach der berühmten Stecknadel im Heuhaufen.

Diese Desorganisation bereitete natürlich auch den Entwicklern des Betriebssystems immer wieder aufs Neue Kopfschmerzen. Mit jeder weiteren neuen Funktion musste die Eindeutigkeit des Bezeichners gewährleistet sein, um Konflikte zu vermeiden. Die Entwickler von Anwendungen wiederum müssen sicherstellen, dass ihre eigenen globalen Funktionsnamen nicht mit denen des Betriebssystems kollidieren.

Dieser Problematik waren sich die Designer der .NET-Plattform wohl bewusst und haben das Konzept der Namespaces (Namensräume) in .NET eingeführt. Namespaces sind hierarchische, logische Organisationsstrukturen. Sie kategorisieren Klassendefinitionen, um das Auffinden einer bestimmten Funktionalität auf ein Minimum an Aufwand zu reduzieren und Mehrdeutigkeiten bei Typangaben zu vermeiden.

Namespaces lassen sich sehr gut mit der Ordnerstruktur eines Dateisystems vergleichen. Dabei ähnelt ein Namenspace einem Verzeichnis. Jedes Verzeichnis enthält Dateien, die meist logisch miteinander in Beziehung stehen: Beispielsweise können die Dateien eine Anwendung bilden, oder es handelt sich um gemeinsam verwaltete Benutzerdokumente. Innerhalb eines Namespaces werden ebenfalls logisch zusammenhängende Klassen verwaltet. Bei dem Vergleich mit dem physikalischen Dateisystem entspricht eine Typdefintion einer Datei. Innerhalb eines Ordners muss der Name einer Datei eindeutig sein – innerhalb eines Namespaces gilt dasselbe für die Typbezeichner. Im Dateisystem können Verzeichnisse Unterverzeichnisse enthalten, um eine feinere Gliederung zu erzielen. Aus denselben Gründen können Namespaces weitere Namespaces einbetten.

Ein Namespace ist ein Verwaltungskonstrukt, in dem eine oder mehrere Typen logisch gruppiert werden. Üblicherweise handelt es sich dabei um Klassen, die funktional in einer verwandtschaftlichen Beziehung stehen. Beispielsweise sind alle Klassen des .NET Frameworks, die Dateioperationen zur Verfügung stellen, dem Namespace System.IO zugeordnet. Der größte Namespace ist der mit der Bezeichnung System. Er enthält die wichtigsten .NET-Typen und hat aus organisatorischen Gründen weitere, untergeordnete Namespaces.

Zwischen einem Namespace und einer Datei, die Typdefinitionen enthält, besteht keine 1:1-Beziehung. Vielmehr kann sich ein Namespace über mehrere Dateien erstrecken. Umgekehrt können in einer Datei auch mehrere Namespaces definiert werden. Ein Datenbanker würde von einer »Viel-zu-viele-Beziehung« sprechen.

Grundsätzlich ist jede Klasse des .NET Frameworks Mitglied eines Namespaces. Folgerichtig wird auch jedweder Programmcode in Namespaces verwaltet. Jedes neue Projekt eröffnet dazu einen neuen Namespace, in dem alle Typen des aktuellen Projekts verwaltet werden.


Galileo Computing

5.7.1 Zugriff auf Namespaces  downtop

Es ist ein Irrtum zu glauben, ohne weitere Maßnahme auf jeden beliebigen Namespace und eine darin verwaltete Klasse Zugriff zu erhalten. Vielmehr muss das Projekt die Datei, die den erforderlichen Namespace veröffentlicht, einbinden.

Damit jedes Projekt schon beim Start eine minimale Grundfunktionalität gewährleisten kann, sind die wichtigsten Dateien – letztendlich also Namespaces – von Anfang an eingebunden. Sie finden die Liste der Dateiverweise im Projektmappen-Explorer, wenn Sie den Knoten Verweise öffnen (siehe Abbildung 5.2).

Damit stehen dem Entwickler schon beim Öffnen eines neuen Projekts sehr viele Klassen mit den grundlegendsten Funktionalitäten zur Verfügung. Sollte es sich im Laufe der Entwicklungszeit herausstellen, dass darüber hinaus noch weitere benötigt werden, muss die Verweisliste ergänzt werden. Dazu ist das Kontextmenü des Knotens Verweise im Projektmappen-Explorer zu öffnen und Verweis hinzufügen... zu wählen. Daraufhin wird das in Abbildung 5.3 dargestellte Dialogfenster angezeigt. In der Registerkarte .NET wird die gewünschte Datei markiert und über die Schaltfläche OK der Liste der ausgewählten Komponenten hinzugefügt.

Abbildung
Hier klicken, um das Bild zu vergrößern

Abbildung 5.2   Die standardmäßige Verweisliste einer Konsolenanwendung

Abbildung
Hier klicken, um das Bild zu vergrößern

Abbildung 5.3   Das Dialogfenster »Verweis hinzufügen«

Wissen Sie, welche Klasse Sie in Ihrem Projekt benötigen, stellt sich nur noch die Frage, in welcher Datei die Klasse zu finden ist. Die Lösung ist sehr einfach, wenn Sie sich das Datenblatt der entsprechenden Klasse in der .NET-Dokumentation ansehen. Darin werden Sie sowohl die Angabe des Namespaces finden, dem die Klasse zugeordnet ist, als auch die Angabe der zugehörigen Datei mit der Dateiendung .dll.


Galileo Computing

5.7.2 Die »using«-Direktive  downtop

Standardmäßig muss beim Zugriff auf eine Klasse mittels Punktnotation auch der Namespace angeführt werden, dem die Klasse zugeordnet ist. Betrachten wir dazu das schon häufig benutzte Beispiel der Methode WriteLine der Klasse Console, die zum Namespace System gehört. Um im Konsolenfenster eine Ausgabe zu erhalten, muss streng genommen


System.Console.WriteLine("Hallo Welt");

codiert werden. Die Angabe aus Namespace und Klassenname wird als voll qualifizierender Name bezeichnet.

Voll qualifizierende Namen führen oft zu sehr langen, unübersichtlichen und schlecht lesbaren Ausdrücken im Programmcode. C# bietet uns mit der using-Direktive Abhilfe. Mit


using System;

kann an späterer Stelle im Programmcode auf alle Typen des angegebenen Namespaces unter Angabe des Typbezeichners zugegriffen werden, ohne den voll qualifizierenden Namen angeben zu müssen:


Console.WriteLine("Hallo Welt");

using-Direktiven stehen außerhalb einer Klassendefinition und sind nur in der deklarierenden Quellcodedatei gültig.


Galileo Computing

5.7.3 Vermeiden von Mehrdeutigkeiten  downtop

Namespaces dienen zur Strukturierung und Gruppierung von Klassen ähnlicher Merkmale, aber auch zur Vermeidung von Mehrdeutigkeiten. Konflikte aufgrund gleicher Typbezeichner schließen Namespaces aus. Allerdings kann using auch neue Probleme bereiten. Existieren nämlich in zwei verschiedenen Namespaces jeweils gleichnamige Typen, hilft using auch nicht weiter. Angenommen, in den beiden fiktiven Namespaces MyApplication und YourApplication wäre jeweils eine Klasse Person definiert, würde das folgende Codefragment wegen der Uneindeutigkeit des Klassennbezeichners einen Fehler verursachen:


using MyApplication;
using YourApplication;
class ClassA {
  static void Main(string[] arr) {   
    Person obj = new Person();
    ...
  }
}

Das Problem lässt sich vermeiden, wenn der Namespace der Klasse Person näher spezifiziert wird, beispielsweise mit:


MyApplication.Person obj = new MyApplication.Person();

Aliasnamen zur Vermeidung von Mehrdeutigkeiten

Es gibt auch noch eine weitere Möglichkeit, um den Eindeutigkeitskonflikt oder eine überlange Namespace-Angabe zu vermeiden: die Definition eines Alias. Allgemein formuliert sieht die vollständige Syntax der using-Direktive folgendermaßen aus:


using [Alias =] Namespace;

Ein Alias ermöglicht noch weitergehende Vereinfachungen: Während die einfache Angabe ohne Alias hinter using nur einen Namespace erlaubt, kann ein Alias sogar für den vollständig qualifizierenden Typbezeichner stehen.

Damit könnten die Klassen Person in den beiden Namespaces auch wie folgt genutzt werden:


using FirstPerson = MyApplication.Person;
using SecondPerson = YourApplication.Person;
...
FirstPerson obj = new FirstPerson();

Genauso können Sie, falls Sie Spaß daran haben, die Klasse Console »umbenennen«, z.B. in Ausgabe:


using Ausgabe = System.Console;
...
Ausgabe.WriteLine("Hallo Welt");

Halten sich aber dabei immer vor Augen, dass ein Alias für einen allgemein bekannten Typbezeichner schlechter interpretierbaren Code zur Folge hat. Daher sollte ein Alias wirklich nur da eingesetzt werden, wo es notwendig ist.


Galileo Computing

5.7.4 Aufrufe mit dem »::«-Operator umleitedowntop

Ein Alias hilft auch dabei, gezielt auf Typen zuzugreifen, wenn ein gleichnamiges Member der Anwendung in der näheren Sichtbarkeitsbereich zu finden ist. Dazu ein Beispiel.


using OuterSystem = System;
class ClassA {
  public static int Console = 23;
  static void Main() {
    OuterSystem.Console.WriteLine(Console);
  }
}

In ClassA ist das Feld Console definiert. Eine gleichnamige Klasse befindet sich auch im Namespace System. Wäre dieser nicht als Alias ansprechbar, würde die Anweisung in Main zu einem Compilerfehler führen, da das Feld Console den Namespace überdeckt.

Ein Alias wird hinter der using-Klausel angegeben und führt zu einem schlecht les- und wartbaren Code. Es noch eine andere Alternative, bei Doppeldeutigkeit den Aufruf zu dem globalen Namespace weiterleiten, nämlich einen Alias einzusetzen. Sehen wir uns die Lösung dazu an:


using System;
class ClassA {
  public static int Console = 23;
  static void Main() {
    global:: System.Console.WriteLine(Console);
  }
}

Die Umleitung zum Namespace wird hier durch global:: ermöglicht. Das Ergebnis des Aufrufs ist das gleiche wie im Codebeispiel zuvor: Es wird die WriteLine-Methode der Klasse System.Console aufgerufen und der Inhalt des Feldes Console angezeigt.

Der »::«-Operator leitet den Aufruf an die global mit using bekannt gegebenen Namespaces weiter. Die Verwendung von global eröffnet die Sichtbarkeit auf die Standardbezeichner der Namespaces, kann aber auch durch einen Alias ersetzt werden.


using NETSystem = System;
...
NETSystem::Console.WriteLine(Console);

Bezogen auf des Codefragment von oben haben Sie folgende Alternativen, den Zugriff auf System.Console zu steuern:


NETSystem.Console.WriteLine(Console);
NETSystem::Console.WriteLine(Console);
global::System.Console.WriteLine(Console);


Galileo Computing

5.7.5 Namespaces festlegen  downtop

Entwickeln Sie ein neues C#-Projekt, wird diesem von der Entwicklungsumgebung automatisch ein Namespace zugeordnet. Standardmäßig entspricht der Name des Namespace dem Namen der Assemblierung (= Projektname). Haben Sie Ihrem Projekt den Namen Meine TolleApplikation gegeben, wird für das Projekt ein gleichnamiger Namespace eröffnet, in dem alle Klassen, Strukturen und Auflistungen definiert werden.

Solange sich Typen innerhalb desselben Namespaces befinden, können sie sich direkt mit ihrem Namen ansprechen. Die Klassen ClassA, ClassB und ClassC des folgenden Codefragments sind demselben Namespace zugeordnet und benötigen deshalb für den gegenseitigen Zugriff keine voll qualifizierende Namensangabe.


namespace MyApplication {
  class ClassA {/*...*/}
  class ClassB {/*...*/}
  class ClassC {/*...*/}
}

In einer Quellcodedatei sind Sie nicht nur auf den automatisch erzeugten Namespace festgelegt, den Sie selbstverständlich nach eigenem Ermessen umbenennen können. Sie können durchaus auch weitere Namespaces eröffnen, wie das folgende Codefragment zeigt:


using System;
using MyApp;
using ConsoleApplication;
namespace ConsoleApplication {
  class ClassA {
    static void Main(string[] args) {
      // erfordert: using MyApp;
      ClassB obj = new ClassB();
    }
  }
}
namespace MyApp {
  public class ClassB {
    public void Test() {
      // erfordert: using ConsoleApplication;
      ClassA obj = new ClassA();
    }
  }
}

Das Beispiel zeigt die beiden parallelen Namespaces ConsoleApplication und MyApp. Jeder enthält eine Klasse mit einer Methode, in der ein Objekt vom Typ der Klasse aus dem anderen Namespace instanziiert wird. Da der Zugriff die Namespaces übergreifend ohne die Angabe des voll qualifizierenden Bezeichners erfolgt, müssen beide Namespaces durch using bekannt gegeben werden.

Eingebettete Namespaces

Ein Namespace kann mit einem Ordner des Dateisystems verglichen werden. So wie ein Ordner einen oder auch mehrere Unterordner enthalten kann, können auch Namespaces eine hierarchische Struktur bilden. Der oberste Namespace, der entweder dem Projektnamen entspricht oder manuell verändert worden ist, bildet die Wurzel der Hierarchie, ähnlich einer Laufwerkangabe.

Soll dieser Stammnamespace eine tiefer gehende Strukturierung aufweisen und eingebettete Namespaces verwalten, wird im äußeren Namespace ein weiterer, untergeordneter Namespace definiert:


namespace Outer {
  class ClassA {
    static void Main(string[] args) {
      ClassB obj = new ClassB();
    }
  }
  namespace Inner {
    class ClassB {
      public void TestProc() {/*...*/}
    }
  }
}

Ein Typ in einem übergeordneten Namespace hat nicht automatisch Zugriff auf einen Typ in einem untergeordneten Namespace. Damit das Codefragment auch tatsächlich fehlerfrei kompiliert werden kann, ist es erforderlich, mit


using Outer.Inner;

den inneren Gültigkeitsbereich den Typen in der übergeordneten Ebene bekannt zu geben.


Galileo Computing

5.7.6 Zusammenfassung  toptop

gp  Alle Klassen des .NET Frameworks sind in Namespaces organisiert. Ein Namespace dient sowohl zum besseren Auffinden eines Typs als auch zur eindeutigen Identifizierung gleichnamiger Typen.
gp  Zwischen einem Namespace und einer Datei besteht keine 1:1-Beziehung. In einer Datei können mehrere Namespaces enthalten sein, gleichzeitig kann sich ein Namespace auch über mehrere Dateien erstrecken.
gp  Standardmäßig verlangt jede Typangabe nach dem voll qualifizierenden Bezeichner. Um zu lange Ausdrücke zu vermeiden, kann mit der using-Direktive ein Pfad auf einen Namespace gelegt werden, so dass im Code nur noch der Klassenbezeichner angegeben werden muss. using-Direktiven beschreiben nur jeweils einen Namespace.
gp  Optional kann der Namespace auch einem Alias zugeteilt werden. In diesem Fall darf auch die Typangabe durch den Alias beschrieben werden.
gp  Namespaces dürfen ineinander verschachtelt werden.
 << zurück
  
  Zum Katalog
Zum Katalog: Visual C# 2005
Visual C# 2005
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Fortgeschrittene Programmierung mit Visual C# 2005






 Fortgeschrittene
 Programmierung
 mit Visual C# 2005


Zum Katalog: Einstieg in Visual C# 2005






 Einstieg in
 Visual C# 2005


Zum Katalog: Einstieg in Visual Basic 2005






 Einstieg in
 Visual Basic 2005


Zum Katalog: Visual Basic 2005






 Visual Basic 2005


Zum Katalog: Java ist auch eine Insel






 Java ist auch eine
 Insel


Zum Katalog: Konzepte und Lösungen für Microsoft-Netzwerke






 Konzepte und
 Lösungen für
 Microsoft-Netzwerke


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo








Copyright © Galileo Press 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de